home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
9-Digit Zip Code Directory
/
9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO
/
z4src.zip
/
DASTRIP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-11
|
11KB
|
380 lines
//----------------------------------------------------------------------------
// MODULE DESCRIPTION
//
// Module: dastrip.c
// Title: Data File Build Utility Library
// Notice: John M. Weeder
// Copyright (c) 1993. All rights reserved.
// This module contains proprietary information and should be
// treated as confidential.
//
//----------------------------------------------------------------------------
// MAINTENANCE HISTORY
//
// $Workfile$
// $Revision$
// $Author$
// $Date$
// $Log$
//
//----------------------------------------------------------------------------
// MODULE NARRATIVE
//
//
// This module contains code to strip a fixed length record file and create a
// delimited data file.
//
// The code in this module should be written entirely in C.
// Do not use any C++ constructs.
//
// This module is portable to:
// DOS 3.X+
// MS Windows 3.X+
// OS/2 2.X+
// OS/2 2.0 PM
// SCO UNIX.
//
// The following compilers are supported:
// MSC 6.0A
// MSC/C++ 7.0
// Borland C++ 3.1 for DOS
// Borland C++ 1.0 for OS/2 2.X
// SCO UNIX cc
//
//----------------------------------------------------------------------------
#include <da.h>
//----------------------------------------------------------------------------
// Global data
//----------------------------------------------------------------------------
typedef struct G // Global data
{
PDATACFG pcfg; // Configuration data
PCHAR pchInput; // Input record buffer
PCHAR pchDelimit; // Delimited record buffer
PCHAR pchInputBuf; // Input record buffer
PCHAR pchDelimitBuf; // Delimited record buffer
PCHAR pchWork; // Work buffer
PDLMNDX pdlmndx; // Delimited record buffer
PDLMNDX pdlmndxBuf; // Delimited index buffer
SIZET cRecords; // Number of records in each pass
SIZET cWork; // Size of work area
HF hfInput; // Input file
HF hfDelimit; // Delimited file
HF hfDelimitNdx; // Delimited file index
PFNSTRIPPROC pfn; // Strip function
} G;
static G g;
#define FL_OF (FL_OPEN|FL_READONLY\
|FL_DENYREADWRITE|FL_BINARY)
#define FL_CF (FL_TRUNCATE|FL_CREATE|FL_READWRITE\
|FL_DENYREADWRITE|FL_BINARY)
//----------------------------------------------------------------------------
// Prototypes
//----------------------------------------------------------------------------
static SIZET FN_L DataStripDelimit(void);
static BOOL FN_L DataStripFile(void);
static BOOL FN_L DataStripProcess(void);
//----------------------------------------------------------------------------
// Description: Strip a data file
// Parameters: pcfg Configuration file data.
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_E DataStrip(PDATACFG pcfg, PFNSTRIPPROC _pfn)
{
BOOL fResult;
TIMET timetElapsed = time(NULL);
Assert(pcfg);
memset(&g, 0, sizeof(g)); // Initialize file handles
g.pcfg = pcfg;
g.hfInput = -1;
g.hfDelimit = -1;
g.hfDelimitNdx = -1;
g.pfn = _pfn;
fResult = DataStripFile();
if (g.hfInput >= 0) // Close input files
FileClose(g.hfInput);
if (g.hfDelimit >= 0)
FileClose(g.hfDelimit);
if (g.hfDelimitNdx >= 0)
FileClose(g.hfDelimitNdx);
if (g.pchInputBuf)
MemFree(g.pchInputBuf);
if (g.pchWork)
MemFree(g.pchWork);
if (g.pchDelimitBuf)
MemFree(g.pchDelimitBuf);
if (g.pdlmndxBuf)
MemFree(g.pdlmndxBuf);
if (g.pcfg->fVerbose)
{
timetElapsed = time(NULL) - timetElapsed;
Output("Elapsed time %ld days, %ld hours, %ld minutes, %ld seconds.\n",
DAYS(timetElapsed), HOURS(timetElapsed),
MINUTES(timetElapsed), SECONDS(timetElapsed));
}
return fResult;
}
//----------------------------------------------------------------------------
// Description: Strip spaces from fixed length file.
// The last field is not null terminated!
// Parameters:
// Returns: Total length of buffer
//----------------------------------------------------------------------------
static SIZET FN_L DataStripDelimit(void)
{
SIZET i, cFields = g.pcfg->cFields;
SIZET cTotal;
PBYTE pb;
PSZ apsz[MAX_FIELDS+1]; // Pointers to fields
PRECID precid1, precid2;
//
// Copy the record into a work area and null terminate the
// strings.
//
memset(g.pchWork, 0, g.cWork); // Zero to start
pb = (PBYTE)g.pchWork;
precid1 = (PRECID)pb;
pb += sizeof(RECID);
for (i = 0; i < cFields; ++i)
{
apsz[i] = (PSZ)pb;
if (!BTEST(g.pcfg->afld[i].fs, FLD_USER))
{
memcpy(apsz[i], g.pchInput + g.pcfg->afld[i].cPos, g.pcfg->afld[i].cLen);
if (BTEST(g.pcfg->afld[i].fs, FLD_NUMERIC))
{
strcpy(apsz[i], strskipzero(apsz[i]));
}
if (!BTEST(g.pcfg->afld[i].fs, FLD_FIXED))
strtrim(apsz[i]); // Trim spaces
}
pb += g.pcfg->afld[i].cLen + 1;
}
apsz[i] = NULL;
//
// Call the user function for initial processing
//
if (g.pfn) // Call user function for processing!
g.pfn(g.pcfg, precid1, apsz, (PBYTE)g.pchInput);
//
// Copy the record into the output area!
//
pb = (PBYTE)g.pchDelimit;
precid2 = (PRECID)pb; // Set cross reference indicator!
*precid2 = *precid1;
cTotal = sizeof(RECID);
pb += sizeof(RECID);
for (i = 0; i < cFields; ++i)
{
SIZET cLen;
if (BTEST(g.pcfg->afld[i].fs, FLD_FIXED))
{
cLen = g.pcfg->afld[i].cLen;
memcpy(pb, apsz[i], cLen);
pb += cLen;
cTotal += cLen;
}
else
{
strtrim(apsz[i]);
cLen = strlen(apsz[i]);
Assert(cLen <= MAX_FIELD_LEN);
*pb++ = (BYTE)cLen;
cTotal++;
if (cLen)
{
memcpy(pb, apsz[i], cLen);
pb += cLen;
cTotal += cLen;
}
}
}
Assert(cTotal <= g.cWork);
return cTotal;
}
//----------------------------------------------------------------------------
// Description: Open and process fixed length file.
// Parameters:
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
static BOOL FN_L DataStripFile(void)
{
SIZET cMax;
BOOL fResult;
if (!FileOpen(&g.hfInput, g.pcfg->szInput, FL_OF, NULL))
return FALSE;
if (g.pcfg->fVerbose)
Output("Opened input file '%s'\n", g.pcfg->szInput);
if (!FileOpen(&g.hfDelimit, g.pcfg->szDelimit, FL_CF, NULL))
return FALSE;
if (g.pcfg->fVerbose)
Output("Opened delimited file '%s'\n", g.pcfg->szDelimit);
if (!FileOpen(&g.hfDelimitNdx, g.pcfg->szDelimitNdx, FL_CF, NULL))
return FALSE;
if (g.pcfg->fVerbose)
Output("Opened delimited index file '%s'\n", g.pcfg->szDelimitNdx);
#if OS_UNIX
cMax = 1024 _K;
#else
cMax = 0xFF00;
#endif
g.cWork = g.pcfg->cUserLen + g.pcfg->cRecLen + g.pcfg->cFields + sizeof(RECID);
g.cRecords = cMax / g.cWork;
g.cRecords = MIN(g.cRecords, cMax / sizeof(DLMNDX));
g.pchInputBuf = MemAlloc(g.cRecords * g.pcfg->cRecLen);
g.pchWork = MemAlloc(g.cWork);
g.pchDelimitBuf = MemAlloc(g.cRecords * g.cWork);
g.pdlmndxBuf = MemAlloc(g.cRecords * sizeof(DLMNDX));
if (g.pchInputBuf == NULL
|| g.pchWork == NULL
|| g.pchDelimitBuf == NULL
|| g.pdlmndxBuf == NULL)
return ErrorNoMem();
if (g.pfn)
g.pfn(g.pcfg, NULL, NULL, NULL);
fResult = DataStripProcess();
if (g.pfn)
g.pfn(g.pcfg, NULL, NULL, NULL);
return fResult;
}
//----------------------------------------------------------------------------
// Description: Process records in fixed length file.
// Parameters: pg Pointer to global variables.
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
static BOOL FN_L DataStripProcess(void)
{
FPOS fpos, fsize;
LONG lRec = 0, lRecs;
SIZET cSize;
SIZET i;
SIZET cDelimitBuf;
LONG lMax = 0;
LONG lSkip = 0;
if (!g.pcfg->fRecord)
return Error("Expected record definition to be specified.");
fsize = FileGetSize(g.hfInput);
if (fsize < 0)
return FALSE;
if (g.pcfg->fSkipFirst)
{
if (g.pcfg->lSkipFirst == 0)
lSkip = (LONG)g.pcfg->cRecLen;
else
lSkip = (LONG)g.pcfg->lSkipFirst;
}
fsize -= lSkip;
lRecs = fsize / (FPOS)g.pcfg->cRecLen;
if (fsize <= 0 // Allow one extra byte for Ctrl-Z
|| lRecs == 0
|| ((fsize % (FPOS)g.pcfg->cRecLen) > 1))
Error("Input file has an invalid number of records.");
fpos = (FPOS)lSkip;
if (!FileSetPos(g.hfInput, fpos, FL_BEGIN))
return FALSE;
fpos = 0;
Output("\nProcessing %ld records\n", lRecs);
#if OS_DOS ||OS_OS2
Output("Press <ESC> to abort processing...\n");
#endif
Output("\n");
for (lRec = 0; lRec < lRecs; )
{
if (g.pcfg->fVerbose)
{
#if OS_UNIX
Output("%-10ld\n", lRec);
#else
Output("\r%-10ld", lRec);
#endif
while (KbdReady())
if (KbdChar() == '\x1B')
{
Output("\r%-20s\rAborted.\n", "");
return FALSE;
}
}
if (g.cRecords > (ULONG)lRecs - (ULONG)lRec) // Handle a partial buffer
g.cRecords = (SIZET)(lRecs - lRec);
if (!FileRead(g.hfInput, g.pchInputBuf, g.cRecords * g.pcfg->cRecLen, -1))
return FALSE;
cDelimitBuf = 0;
g.pchInput = g.pchInputBuf;
g.pchDelimit = g.pchDelimitBuf;
g.pdlmndx = g.pdlmndxBuf;
for (i = 0; i < g.cRecords; ++i)
{
cSize = DataStripDelimit();
g.pdlmndx->fpos = fpos;
g.pdlmndx->usLen = (USHORT)cSize;
lMax = MAX((LONG)lMax, (LONG)cSize);
fpos += (FPOS)cSize;
cDelimitBuf += cSize;
g.pchDelimit += cSize;
g.pchInput += g.pcfg->cRecLen;
g.pdlmndx++;
}
if (!FileWrite(g.hfDelimit, g.pchDelimitBuf, cDelimitBuf, -1))
return FALSE;
if (!FileWrite(g.hfDelimitNdx, g.pdlmndxBuf, g.cRecords * sizeof(DLMNDX), -1))
return FALSE;
lRec += g.cRecords;
}
if (g.pcfg->fVerbose)
{
#if OS_UNIX == 0
Output("\r%-20s\r", "");
#endif
Output("Processed %ld of %ld records.\n", lRec, lRecs);
Output("Average size was %ld bytes.\n", (LONG)(fpos / lRecs));
Output("Maximum size was %ld bytes.\n", lMax);
Output("Total size was %ld data, %ld index, %ld total.\n",
(LONG)fpos, (LONG)sizeof(DLMNDX) * lRecs,
(LONG)fpos + (LONG)sizeof(DLMNDX) * lRecs);
}
return TRUE;
}
//----------------------------------------------------------------------------
//------------------------------- End of File --------------------------------
//----------------------------------------------------------------------------